home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
tools
/
mg
/
src.lzh
/
amiga
/
ttymenu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-23
|
20KB
|
764 lines
/*
* ttymenu.c
*
* Incorporates the browser, for rummaging around on disks, and the usual Emacs
* editing command menu
*
* Copyright (c) 1986, Mike Meyer Mic Kaczmarczik did a few things along the
* way.
*
* Permission is hereby granted to distribute this program, so long as this
* source file is distributed with it, and this copyright notice is not
* removed from the file.
*
*/
#include "do_menu.h"
#ifdef DO_MENU
#include <exec/types.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <intuition/intuition.h>
#ifdef LATTICE
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/exec.h>
#else
#include <functions.h>
#endif
#undef MANX
#undef LATTICE
#undef AZTEC
#include "compiler.h"
#include "no_macro.h"
#include "no_dired.h"
#include "gosmacs.h"
#include "browser.h"
#include "change_font.h"
#include "menu.h"
#undef TRUE
#undef FALSE
#include "def.h"
#ifdef BROWSER
#include "buffer.h"
#endif
#include "window.h"
#ifdef BROWSER
static int Add_Dir PROTO((char *dir, char *name));
static void Add_Devices PROTO((ULONG devtype));
#endif
extern struct Menu *AutoMenu;
extern struct Window *EmW;
#define MNUM(menu,item,sub) (SHIFTMENU(menu)|SHIFTITEM(item)|SHIFTSUB(sub))
#ifdef BROWSER
#define LONGEST_NAME 80 /* Longest file name we can deal with */
# ifdef ANSI
#include <string.h>
#include <stdlib.h>
# else
char *index(); /* find first instance of c in s */
#define strchr(s, c) index(s, c)
# endif
# ifdef MENU
#define FIRSTMENU 1
# else
#define FIRSTMENU 0
# endif
#endif
#ifdef MENU
/*
* When ttgetc() sees a menu selection event, it stuffs the sequence KMENU
* <menu><item><subitem> into the input buffer
*
* The menu item names are chosen to be relatively close to the extended
* function names, so a user can usually figure out the key binding of a menu
* item by searching through the "display-bindings" buffer for something
* that's close.
*/
/*
* Commands for managing files and buffers
*/
extern int filevisit();
extern int poptofile();
extern int fileinsert();
extern int filesave();
extern int filewrite();
#ifndef NO_DIRED
extern int dired();
#endif
extern int usebuffer();
extern int poptobuffer();
extern int killbuffer();
extern int listbuffers();
extern int savebuffers();
extern int quit();
static struct MenuBinding FileItems[] = {
{"Find File C-x C-f", filevisit},
{"Pop To File C-x 4 f", poptofile},
{"Insert File C-x i", fileinsert},
{"Save File C-x C-s", filesave},
{"Write File C-x C-w", filewrite},
#ifndef NO_DIRED
{"Dired C-x d", dired},
#endif
{"Switch To Buffer C-x b", usebuffer},
{"Pop To Buffer C-x 4 b", poptobuffer},
{"Kill Buffer C-x k", killbuffer},
{"List Buffers C-x C-b", listbuffers},
{"Save Buffers C-x s", savebuffers},
{"Save And Exit C-x C-c", quit}
};
/*
* Commands for various editing functions
*/
extern int yank();
extern int openline();
extern int killline();
extern int deblank();
extern int justone();
extern int indent();
extern int twiddle();
extern int quote();
static struct MenuBinding EditItems[] = {
{"Yank C-y", yank},
{"Blank Line C-o ", openline},
{"Kill Line C-k", killline},
{"Delete Blank Lines C-x C-o", deblank},
{"Delete Blanks M-SPC", justone},
{"Newline And Indent C-j", indent},
{"Transpose Characters C-t", twiddle},
{"Quoted Insert C-q", quote}
};
/*
* Movement commands
*/
extern int forwpage();
extern int backpage();
extern int gotobol();
extern int gotobob();
extern int gotoeol();
extern int gotoeob();
extern int gotoline();
extern int showcpos();
static struct MenuBinding MoveItems[] = {
{"Scroll Up C-v", forwpage},
{"Scroll Down M-v", backpage},
{"Start Of Line C-a", gotobol},
{"Start Of Buffer M-<", gotobob},
{"End Of Line C-e", gotoeol},
{"End Of Buffer M->", gotoeob},
{"Goto Line", gotoline},
{"Show Cursor C-x =", showcpos}
};
/*
* Commands for searching and replacing
*/
extern int forwisearch();
extern int backisearch();
extern int searchagain();
extern int forwsearch();
extern int backsearch();
extern int queryrepl();
static struct MenuBinding SearchItems[] = {
{"I-Search Forward C-s", forwisearch},
{"I-Search Backward C-r", backisearch},
{"Search Again", searchagain},
{"Search Forward M-s", forwsearch},
{"Search Backward M-r", backsearch},
{"Query Replace M-%", queryrepl}
};
/*
* Commands that manipulate words
*/
extern int forwword();
extern int backword();
extern int delfword();
extern int delbword();
extern int capword();
extern int lowerword();
extern int upperword();
static struct MenuBinding WordItems[] = {
{"Forward Word M-f", forwword},
{"Backward Word M-b", backword},
{"Kill Word M-d", delfword},
{"Backward Kill Word M-DEL", delbword},
{"Capitalize Word M-c", capword},
{"Downcase Word M-l", lowerword},
{"Upcase Word M-u", upperword}
};
/*
* Commands relating to paragraphs
*/
extern int gotoeop();
extern int gotobop();
extern int fillpara();
extern int setfillcol();
extern int killpara();
extern int fillmode();
static struct MenuBinding ParaItems[] = {
{"Forward Paragraph M-]", gotoeop},
{"Backward Paragraph M-[", gotobop},
{"Fill Paragraph M-q", fillpara},
{"Set Fill Column C-x f", setfillcol},
{"Kill Paragraph", killpara},
{"Auto Fill Mode", fillmode}
};
/*
* Region stuff
*/
extern int setmark();
extern int swapmark();
extern int killregion();
extern int copyregion();
extern int lowerregion();
extern int upperregion();
static struct MenuBinding RegionItems[] = {
{"Set Mark C-@", setmark},
{"Exch Point And Mark C-x C-x", swapmark},
{"Kill Region C-w", killregion},
{"Copy Region As Kill M-w", copyregion},
{"Downcase Region C-x C-l", lowerregion},
{"Upcase Region C-x C-u", upperregion}
};
/*
* Commands for manipulating windows
*/
extern int splitwind();
extern int delwind();
extern int onlywind();
extern int nextwind();
#ifdef GOSMACS
extern int prevwind();
#endif
extern int enlargewind();
extern int shrinkwind();
extern int refresh();
extern int reposition();
extern int togglewindow();
#ifdef CHANGE_FONT
extern int setfont();
#endif
static struct MenuBinding WindowItems[] = {
{"Split Window C-x 2", splitwind},
{"Delete Window C-x 0", delwind},
{"Delete Other Windows C-x 1", onlywind},
{"Next Window C-x o", nextwind},
#ifdef GOSMACS
{"Up Window", prevwind},
#endif
{"Enlarge Window C-x ^", enlargewind},
{"Shrink Window", shrinkwind},
{"Redraw Display", refresh},
{"Recenter C-l", reposition},
{"Toggle Border", togglewindow},
#ifdef CHANGE_FONT
{"Set Font", setfont}
#endif
};
/*
* Miscellaneous commands
*/
extern int definemacro();
extern int finishmacro();
extern int executemacro();
extern int extend();
extern int bindtokey();
extern int desckey();
extern int wallchart();
extern int showversion();
extern int spawncli();
static struct MenuBinding MiscItems[] = {
#ifndef NO_MACRO
{"Start Kbd Macro C-x (", definemacro},
{"End Kbd Macro C-x )", finishmacro},
{"Call Kbd Macro C-x e", executemacro},
#endif
{"Execute Command M-x", extend},
{"Global Set Key", bindtokey},
{"Describe Key C-h c", desckey},
{"Describe Bindings C-h b", wallchart},
{"Emacs Version", showversion},
{"New CLI C-z", spawncli}
};
/*
* The following table contains the titles, number of items, and pointers to,
* the individual menus.
*/
static struct MenuInfo EMInfo[] = {
{"File ", NITEMS(FileItems), &FileItems[0]},
{"Edit ", NITEMS(EditItems), &EditItems[0]},
{"Move ", NITEMS(MoveItems), &MoveItems[0]},
{"Search ", NITEMS(SearchItems), &SearchItems[0]},
{"Word ", NITEMS(WordItems), &WordItems[0]},
{"Paragraph ", NITEMS(ParaItems), &ParaItems[0]},
{"Region ", NITEMS(RegionItems), &RegionItems[0]},
{"Window ", NITEMS(WindowItems), &WindowItems[0]},
{"Miscellaneous ", NITEMS(MiscItems), &MiscItems[0]}
};
/*
* There are three cases to deal with; the menu alone, the Browser alone, and
* both of them together. We #define some things to make life a little
* easier to deal with
*/
# ifdef BROWSER
# define Edit_Menu_Init() Menu_Add("Edit ", TRUE, FALSE)
# define Edit_Menu_Add(n) Menu_Item_Add(n,(USHORT)ITEMENABLED,0L,(BYTE)0,FALSE)
# define Edit_Item_Add(n) Menu_SubItem_Add(n,(USHORT)ITEMENABLED,0L,(BYTE)0,FALSE)
# else
# define Edit_Menu_Init() cinf = NULL /* harmless */
# define Edit_Menu_Add(n) n[strlen(n)-1] = '\0'; Menu_Add(n, TRUE, FALSE)
# define Edit_Item_Add(n) Menu_Item_Add(n,(USHORT)ITEMENABLED,0L,(BYTE)0,FALSE)
# endif /* BROWSER */
#endif
/*
* Initialize the Emacs menu
*/
struct Menu *
InitEmacsMenu(EmW)
struct Window *EmW;
{
#ifdef MENU
register struct MenuInfo *cinf;
register struct MenuBinding *lastbinding, *cb;
struct MenuInfo *lastinfo;
#endif
Menu_Init(); /* init the menu */
#ifdef MENU
Edit_Menu_Init(); /* Set up for editing menu */
lastinfo = &EMInfo[NITEMS(EMInfo)]; /* loop sentinel */
for (cinf = EMInfo; cinf < lastinfo; cinf++) {
Edit_Menu_Add(cinf->Name);
lastbinding = &cinf->Items[cinf->NumItems];
for (cb = cinf->Items; cb < lastbinding; cb++)
Edit_Item_Add(cb->Command);
}
#endif
#ifdef BROWSER
Menu_Add("Disks ", TRUE, FALSE); /* name is already there */
Add_Devices(DLT_DEVICE);/* devices first */
Add_Devices(DLT_VOLUME);/* mounted volume names next */
Add_Devices(DLT_DIRECTORY); /* assigned directories last */
#endif
return AutoMenu;
}
/*
* amigamenu() -- handles a menu pick.
*/
amigamenu(f, n)
{
unsigned short menunum, itemnum, subnum, Menu_Number;
char *name;
#ifdef MENU
register int (*fp) PROTO((int, int));
#endif
#ifdef BROWSER
register unsigned short level, i, dirp;
register char *cp;
int stat;
struct MenuItem *ItemAddress();
/* State variables that describe the current directory */
static char Dir_Name[LONGEST_NAME];
static unsigned short Menu_Level = 0;
#endif
/* read the menu, item, and subitem codes from the input stream */
menunum = getkey(DISSCR) - MN_OFFSET;
itemnum = getkey(DISSCR) - MN_OFFSET;
subnum = getkey(DISSCR) - MN_OFFSET;
Menu_Number = (USHORT)
(SHIFTMENU(menunum) | SHIFTITEM(itemnum) | SHIFTSUB(subnum));
#ifndef BROWSER
# ifdef MENU
fp = EMInfo[menunum].Items[itemnum].Function;
return (*(fp) (f, n));
# endif
#else /* we're using the Browser */
# ifdef MENU
/* Handle commands from the Edit menu when using the Browser */
if (0 == menunum) {
fp = EMInfo[itemnum].Items[subnum].Function;
return ((*fp) (f, n));
}
# endif
/* Here when a selection was made in a Browser menu */
name = (char *) ((struct IntuiText *)
(ItemAddress(AutoMenu, (ULONG) Menu_Number)->ItemFill))
->IText;
level = MENUNUM(Menu_Number) - FIRSTMENU;
/* Got what we want, so clear the menu to avoid confusing the user */
ClearMenuStrip(EmW);
/* set dirp to FALSE if the name is not a directory or disk */
dirp = (strchr(name, '/') != NULL || strchr(name, ':') != NULL);
/* First, set the directory name right */
if (level > Menu_Level) /* Not possible, die */
panic("impossible menu_level in amigamenu");
else if (level == 0) /* picked a new disk */
Dir_Name[0] = '\0';
else if (level < Menu_Level) { /* Throw away some levels */
for (i = 1, cp = strchr(Dir_Name, ':'); i < level; i++) {
if (cp == NULL)
return FALSE;
cp = strchr(cp, '/');
}
if (cp == NULL)
panic("broken file name in amigamenu");
*++cp = '\0';
}
/* else Menu_Level == level, chose a file a current level */
/* Now, fix up the menu and it's state variable */
while (Menu_Level > level) {
Menu_Level--;
Menu_Pop();
}
/*
* If we added a file, visit it, else add a new directory level to
* the menu.
*/
if (!dirp)
stat = Display_File(Dir_Name, name);
else {
Menu_Level++;
(void) strncat(Dir_Name, name,
LONGEST_NAME - strlen(Dir_Name) - 1);
stat = Add_Dir(Dir_Name, name);
}
SetMenuStrip(EmW, AutoMenu);
return stat;
#endif
}
#ifdef BROWSER
/*
* Display_File - Go fetch a the requested file into a window.
*/
Display_File(dir, file)
char *dir, *file;
{
register struct buffer *bp, *findbuffer();
char File_Name[LONGEST_NAME], *fn, *adjustname();
if (!dir || !file)
return FALSE;
(void) strcpy(File_Name, dir);
(void) strncat(File_Name, file, LONGEST_NAME - strlen(File_Name) - 1);
fn = adjustname(File_Name);
if ((bp = findbuffer(fn)) == NULL)
return FALSE;
curbp = bp;
if (showbuffer(bp, curwp, WFHARD) != TRUE)
return FALSE;
if (bp->b_fname[0] == 0)
return (readin(fn)); /* Read it in. */
return TRUE;
}
struct name_node {
char *name;
struct name_node *next;
};
static void free_name_list PROTO((struct name_node * name_list));
static void
free_name_list(name_list)
register struct name_node *name_list;
{
register struct name_node *tmp;
while (name_list) {
tmp = name_list;
name_list = name_list->next;
free(tmp->name);
free(tmp);
}
}
/*
* Add_Dir - given a dir and a name, add the menu name with the files in dir
* as entries. Use AllocMem() in order to make sure the file info block is
* on a longword boundary.
*/
static
Add_Dir(dir, name)
char *dir, *name;
{
register char *last_char;
BPTR my_lock;
unsigned short count;
int stat = FALSE;
static char Name_Buf[LONGEST_NAME];
struct FileInfoBlock *File_Info;
struct name_node *name_list, *tmp_name;
char *cp, **name_table;
int i;
if ((File_Info = (struct FileInfoBlock *)
AllocMem((LONG) sizeof(struct FileInfoBlock), 0L)) == NULL)
return (FALSE);
/* Fix up the trailing / if it needs it */
last_char = &dir[strlen(dir) - 1];
if (*last_char == '/')
*last_char = '\0';
/* Now, start on the directory */
if ((my_lock = Lock(dir, ACCESS_READ)) == NULL)
goto out;
if (!Examine(my_lock, File_Info))
goto out;
if (File_Info->fib_DirEntryType < 0L)
goto out;
if (Menu_Add(name, TRUE, TRUE) == 0)
goto out;
name_list = NULL;
for (count = 0; ExNext(my_lock, File_Info)
|| IoErr() != ERROR_NO_MORE_ENTRIES; count++) {
(void) strcpy(Name_Buf, File_Info->fib_FileName);
if (File_Info->fib_DirEntryType >= 0L) {
(void) strcat(Name_Buf, "/");
}
if (!(cp = malloc(strlen(Name_Buf) + 1))) {
free_name_list(name_list);
return (FALSE);
}
strcpy(cp, Name_Buf);
if (!(tmp_name = (struct name_node *)
malloc(sizeof(struct name_node)))) {
free_name_list(name_list);
return (FALSE);
}
tmp_name->name = cp;
tmp_name->next = name_list;
name_list = tmp_name;
}
if (count > 0) {
if (!(name_table = (char **) malloc(count * sizeof(char *)))) {
free_name_list(name_list);
return (FALSE);
}
i = count;
for (tmp_name = name_list; tmp_name;
tmp_name = tmp_name->next) {
name_table[--i] = tmp_name->name;
}
tqsort(name_table, count);
for (i = 0; i < count; i++) {
if (Menu_Item_Add(name_table[i],
(USHORT) ITEMENABLED, 0L, (BYTE) 0, TRUE)
== MNUM(NOMENU, NOITEM, NOSUB))
break;
}
free_name_list(name_list);
free(name_table);
} else
Menu_Item_Add("EMPTY", (USHORT) 0, 0L, (BYTE) 0, FALSE);
/* Put everything back */
if (*last_char == '\0')
*last_char = '/';
stat = TRUE;
out:
UnLock(my_lock);
FreeMem(File_Info, (LONG) sizeof(struct FileInfoBlock));
return stat;
}
/*
* Add all the devices currently known by the system to the current menu,
* based on the type of device list entry desired. Disable multitasking
* while we look inside the device list, so we don't fly off into space while
* traversing it.
*/
struct DosLibrary *DosBase;
static VOID
Add_Devices(devtype)
ULONG devtype;
{
register struct DeviceList *devlist;
struct RootNode *rootnode;
struct DosInfo *dosinfo;
UBYTE buffer[80];
int ramflag = 0;
struct name_node *name_list, *tmp_name;
char *cp, **name_table;
int count, i;
/* if you've gotten this far, none of these will be null. */
DosBase = (struct DosLibrary *) OpenLibrary(DOSNAME, 0L);
Forbid(); /* let's be careful out there... */
rootnode = (struct RootNode *) DosBase->dl_Root;
dosinfo = (struct DosInfo *) BADDR(rootnode->rn_Info);
devlist = (struct DeviceList *) BADDR(dosinfo->di_DevInfo);
name_list = NULL;
count = 0;
while (devlist) {
/* select by specified device type */
if (devlist->dl_Type != devtype) {
devlist = (struct DeviceList *) BADDR(devlist->dl_Next);
continue;
}
/* convert device's name into AmigaDOS name and concat a ":" */
btocstr((BPTR) devlist->dl_Name, buffer, sizeof(buffer));
strcat(buffer, ":");
/*
* Always add volumes and assigned directories. However,
* disks should be the only devices added to the list. Magic
* disk test courtesy of Phillip Lindsay, Commodore-Amiga
* Inc.
*/
if (devtype != DLT_DEVICE || devlist->dl_Task) {
count++;
if (!(cp = malloc(strlen(buffer) + 1))) {
free_name_list(name_list);
Permit();
CloseLibrary((struct Library *) DosBase);
return;
}
strcpy(cp, buffer);
if (!(tmp_name = (struct name_node *)
malloc(sizeof(struct name_node)))) {
free_name_list(name_list);
Permit();
CloseLibrary((struct Library *) DosBase);
return;
}
tmp_name->name = cp;
tmp_name->next = name_list;
name_list = tmp_name;
if (devtype == DLT_DEVICE &&
!strcmp(buffer, "RAM:"))
ramflag = 1;
}
devlist = (struct DeviceList *) BADDR(devlist->dl_Next);
}
Permit();
CloseLibrary((struct Library *) DosBase);
if (count > 0 || (devtype == DLT_DEVICE && !ramflag)) {
if (!(name_table = (char **)
malloc((count + 1) * sizeof(char *)))) {
free_name_list(name_list);
return;
}
name_table[count] = "RAM:";
i = count;
for (tmp_name = name_list; tmp_name;
tmp_name = tmp_name->next) {
name_table[--i] = tmp_name->name;
}
if (devtype == DLT_DEVICE && !ramflag)
count++;
tqsort(name_table, count);
for (i = 0; i < count; i++) {
if (Menu_Item_Add(name_table[i],
(USHORT) ITEMENABLED, 0L, (BYTE) 0, TRUE)
== MNUM(NOMENU, NOITEM, NOSUB))
break;
}
free_name_list(name_list);
free(name_table);
}
}
btocstr(bp, buf, bufsiz)
BPTR bp;
char *buf;
int bufsiz;
{
register UBYTE *cp;
register int len, i;
cp = (UBYTE *) BADDR(bp);
len = (int) *(cp++);
len = (len > bufsiz) ? bufsiz : len; /* truncate if necessary */
for (i = 0; i < len; i++)
buf[i] = *(cp++);
buf[i] = '\0';
return (len < bufsiz); /* return FALSE if truncated */
}
#ifndef LATTICE
tqsort(v, n)
register char **v;
int n;
{
register char *temp;
register int gap, j, i;
for (gap = n / 2; gap > 0; gap /= 2)
for (i = gap; i < n; i++)
for (j = i - gap; j >= 0; j -= gap)
if (strcmp(v[j], v[j + gap]) > 0) {
/* exchange them */
temp = v[j];
v[j] = v[j + gap];
v[j + gap] = temp;
}
}
#endif
#endif
#else /* DO_MENU */
#include "nullfile.h"
#endif